import pandas as pd
pd.set_option('display.expand_frame_repr', False)
import matplotlib
import matplotlib.pyplot as plt
font = {'size' : 20}
matplotlib.rc('font', **font)
from pylab import rcParams
rcParams["figure.figsize"] = 30,16
import seaborn as sns
from statsmodels.tsa.statespace.sarimax import SARIMAX
from pmdarima.arima import auto_arima
from sklearn.preprocessing import MinMaxScaler
import joblib
import warnings
warnings.filterwarnings("ignore")
import sys
sys.path.insert(0, "../")
import functions
#Unskalierte Daten für Analysen laden
df_unscaled = pd.read_csv("../3-Data Preparation/data.csv", index_col=0, parse_dates=True)
df_unscaled.index.freq = "D"
#Wahre Werte der Testdaten
y_true = df_unscaled["verbrauch"]["2021-01-01":]
#Skalierte Daten für Modellierung laden
df_scaled = pd.read_csv("../3-Data Preparation/data_scaled.csv", index_col=0, parse_dates=True)
df_scaled.index.freq = "D"
#Abspalten der endogenen Daten
endog_train = df_scaled["verbrauch"][:"2020-12-31"]
endog_test = df_scaled["verbrauch"]["2021-01-01":]
endog = endog_train.append(endog_test)
Es wird zunächst die Funktion auto_airma() verwendet, um einen geeigneten Parametersatz zu finden.
Die Funktion ermittelt ein ARIMA(2,0,2)(2,0,2)7 als bestes Modell. Es ist dabei zu erkennen, dass die Funktion höchstens Module dritter Ordnung verwendet. Darüber hinaus scheinen zusätzliche Lags keine ausreichenden Verbesserungen zu erzielen.
model = auto_arima(y=endog, seasonal=True, m=7, d=0, D=0, information_criterion="aic", trace=True)
Performing stepwise search to minimize aic ARIMA(2,0,2)(1,0,1)[7] intercept : AIC=-5830.350, Time=4.60 sec ARIMA(0,0,0)(0,0,0)[7] intercept : AIC=-705.558, Time=0.20 sec ARIMA(1,0,0)(1,0,0)[7] intercept : AIC=-4833.713, Time=1.79 sec ARIMA(0,0,1)(0,0,1)[7] intercept : AIC=-3350.364, Time=1.04 sec ARIMA(0,0,0)(0,0,0)[7] : AIC=4297.801, Time=0.11 sec ARIMA(2,0,2)(0,0,1)[7] intercept : AIC=-3440.116, Time=3.71 sec ARIMA(2,0,2)(1,0,0)[7] intercept : AIC=-4797.181, Time=3.95 sec ARIMA(2,0,2)(2,0,1)[7] intercept : AIC=-5824.050, Time=7.09 sec ARIMA(2,0,2)(1,0,2)[7] intercept : AIC=-5777.461, Time=9.22 sec ARIMA(2,0,2)(0,0,0)[7] intercept : AIC=-2210.906, Time=1.99 sec ARIMA(2,0,2)(0,0,2)[7] intercept : AIC=-3938.336, Time=7.21 sec ARIMA(2,0,2)(2,0,0)[7] intercept : AIC=-5236.242, Time=6.53 sec ARIMA(2,0,2)(2,0,2)[7] intercept : AIC=-5948.055, Time=10.27 sec ARIMA(1,0,2)(2,0,2)[7] intercept : AIC=inf, Time=8.71 sec ARIMA(2,0,1)(2,0,2)[7] intercept : AIC=-5824.093, Time=7.98 sec ARIMA(3,0,2)(2,0,2)[7] intercept : AIC=-5508.323, Time=15.84 sec ARIMA(2,0,3)(2,0,2)[7] intercept : AIC=-5472.185, Time=11.56 sec ARIMA(1,0,1)(2,0,2)[7] intercept : AIC=-5852.356, Time=7.06 sec ARIMA(1,0,3)(2,0,2)[7] intercept : AIC=-5888.663, Time=9.38 sec ARIMA(3,0,1)(2,0,2)[7] intercept : AIC=-5922.667, Time=9.41 sec ARIMA(3,0,3)(2,0,2)[7] intercept : AIC=-5859.165, Time=12.10 sec ARIMA(2,0,2)(2,0,2)[7] : AIC=inf, Time=5.48 sec Best model: ARIMA(2,0,2)(2,0,2)[7] intercept Total fit time: 145.221 seconds
Mit einem MAPE von 3,21% ist das Modell bereits sehr nah an den tatsächlichen Werten. Die wöchentliche und jährliche Saisonalität kann gut erfasst werden. Die Log-Likelihood von 3.038 und das AIC von -6.058 lassen sich nicht absolut interpretieren und können daher erst im Kontext weiterer Modelle bewertet werden. In der Spalte „P>|Z|“ lassen sich die p-Werte der einzelnen Koeffizienten der Module ablesen. Es ist zu erkennen, dass einzelne Koeffizienten insignifikant sind. Das bedeutet zwar nicht zwangsweise, dass diese Koeffizienten keine Generalisierung erzielen, allerdings bietet es sich an, ein Modell ohne die insignifikanten Lags zu testen.
#Nicht-saisonale und saisonale Ordnung festlegen
order = (2, 0, 2) #p, d, q
seasonal_order = (2, 0, 2, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
=========================================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(2, 0, 2)x(2, 0, 2, 7) Log Likelihood 3037.805
Date: Thu, 03 Feb 2022 AIC -6057.610
Time: 10:32:49 BIC -6004.991
Sample: 01-01-2015 HQIC -6038.529
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 0.9434 0.050 18.823 0.000 0.845 1.042
ar.L2 0.0162 0.045 0.358 0.720 -0.072 0.105
ma.L1 -0.2361 0.051 -4.665 0.000 -0.335 -0.137
ma.L2 -0.2770 0.022 -12.526 0.000 -0.320 -0.234
ar.S.L7 0.0215 0.056 0.383 0.702 -0.088 0.131
ar.S.L14 0.9783 0.056 17.455 0.000 0.868 1.088
ma.S.L7 0.0038 0.052 0.074 0.941 -0.098 0.106
ma.S.L14 -0.9595 0.051 -18.780 0.000 -1.060 -0.859
sigma2 0.0055 6.28e-05 87.433 0.000 0.005 0.006
===================================================================================
Ljung-Box (L1) (Q): 0.02 Jarque-Bera (JB): 15797.82
Prob(Q): 0.89 Prob(JB): 0.00
Heteroskedasticity (H): 0.81 Skew: -1.94
Prob(H) (two-sided): 0.00 Kurtosis: 14.54
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds = model.predict(start="2021-01-01", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds)
Vorhersage
R2 0.89
MAE 5379.0
MSE 77296958.0
RMSE 8792.0
MAPE 3.21 %
Es werden das zweie Lag beim AR-Modul und die ersten Lags bei den SAR- und SMA-Modulen entfernt. Dadurch verschlechtern sich MAPE, Log-Likelihood und AIC ein wenig. Die Lags werden zwar als insignifikant erkannt, allerdings scheint es sich nicht um einen Fall von Überanpassung zu handeln. Außerdem fällt auch das AIC, die zusätzlichen Lags scheinen dem Modell also doch einen gewissen Informationsgehalt zu bieten.
#Nicht-saisonale und saisonale Ordnung festlegen
order = (1, 0, 2) #p, d, q
seasonal_order = ([2], 0, [2], 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
===========================================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(1, 0, 2)x([2], 0, 2, 7) Log Likelihood 2971.115
Date: Thu, 03 Feb 2022 AIC -5930.231
Time: 10:32:54 BIC -5895.151
Sample: 01-01-2015 HQIC -5917.510
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 0.9999 8.16e-05 1.23e+04 0.000 1.000 1.000
ma.L1 -0.2655 0.006 -46.836 0.000 -0.277 -0.254
ma.L2 -0.3070 0.012 -25.105 0.000 -0.331 -0.283
ar.S.L14 0.9994 0.000 4095.178 0.000 0.999 1.000
ma.S.L14 -0.9576 0.008 -119.465 0.000 -0.973 -0.942
sigma2 0.0054 6.14e-05 88.203 0.000 0.005 0.006
===================================================================================
Ljung-Box (L1) (Q): 0.08 Jarque-Bera (JB): 11683.50
Prob(Q): 0.78 Prob(JB): 0.00
Heteroskedasticity (H): 0.80 Skew: -1.54
Prob(H) (two-sided): 0.00 Kurtosis: 13.01
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.89
MAE 5521.0
MSE 80000959.0
RMSE 8944.0
MAPE 3.32 %
Die von der auto_arima()-Funktion ermittelten Parameter erzielen zwar gute Ergebnisse, allerdings ist die Funktion selbstverständlich nicht zu 100 % zuverlässig. Es wird daher weiterhin versucht, mit Hilfe der ACF/PACF und der Auswertung der einzelnen Modelle eine Ordnung zu finden, die bessere Ergebnisse erzielt.
Wenn die dritten Ordnungen der Module verwendet werden, führt dies zu keiner Verbesserung des Modells. Der MAPE fällt auf 3,25%, Die Log-Likelihood fällt auf 3.003 ab und auch das AIC steigt auf -5.979. Es handelt sich zwar um eine leichte Verbesserung im Vergleich zum ARIMA(1,0,2)([2],0,[2])7, jedoch kann das initiale Modell ARIMA(2,0,2)(2,0,2) nicht übertroffen werden, obwohl sehr viel mehr Lags benutzt werden. Obwohl die Log-Likelihood im Vergleich zum initialen Modell fällt, kann eine Überanpassung nicht ausgeschlossen werden, da sehr viele Koeffizienten insignifikant sind.
#Nicht-saisonale und saisonale Ordnung festlegen
order = (3, 0, 3) #p, d, q
seasonal_order = (3, 0, 3, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
=========================================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(3, 0, 3)x(3, 0, 3, 7) Log Likelihood 3002.533
Date: Thu, 03 Feb 2022 AIC -5979.065
Time: 10:39:25 BIC -5903.060
Sample: 01-01-2015 HQIC -5951.503
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 2.2915 0.068 33.749 0.000 2.158 2.425
ar.L2 -1.8116 0.120 -15.130 0.000 -2.046 -1.577
ar.L3 0.5001 0.060 8.387 0.000 0.383 0.617
ma.L1 -1.5806 0.069 -22.960 0.000 -1.716 -1.446
ma.L2 0.6587 0.089 7.423 0.000 0.485 0.833
ma.L3 0.0616 0.032 1.931 0.053 -0.001 0.124
ar.S.L7 0.0437 0.820 0.053 0.958 -1.564 1.651
ar.S.L14 0.3657 0.796 0.459 0.646 -1.195 1.926
ar.S.L21 0.5877 0.732 0.803 0.422 -0.846 2.022
ma.S.L7 -0.0017 0.829 -0.002 0.998 -1.626 1.623
ma.S.L14 -0.3223 0.781 -0.413 0.680 -1.853 1.208
ma.S.L21 -0.5437 0.703 -0.774 0.439 -1.921 0.834
sigma2 0.0057 7.13e-05 79.739 0.000 0.006 0.006
===================================================================================
Ljung-Box (L1) (Q): 0.34 Jarque-Bera (JB): 15570.40
Prob(Q): 0.56 Prob(JB): 0.00
Heteroskedasticity (H): 0.78 Skew: -1.93
Prob(H) (two-sided): 0.00 Kurtosis: 14.46
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.89
MAE 5451.0
MSE 78895422.0
RMSE 8882.0
MAPE 3.25 %
Werden die insignifikanten Lags aus dem ARIMA(3,0,3)(3,0,3)7 entfernt, nimmt die Güte des Modells sehr stark ab. Es werden praktisch die gesamten saisonalen Komponenten deaktiviert. Dadurch steigt der MAPE auf über 9%, Log-Likelihood und AIC sind ebenfalls sehr schlecht.
#Nicht-saisonale und saisonale Ordnung festlegen
order = (3, 0, 2) #p, d, q
seasonal_order = (0, 0, 0, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
==============================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(3, 0, 2) Log Likelihood 1103.072
Date: Thu, 03 Feb 2022 AIC -2194.143
Time: 10:41:49 BIC -2159.064
Sample: 01-01-2015 HQIC -2181.422
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 0.5549 0.001 822.152 0.000 0.554 0.556
ar.L2 -0.5538 0.001 -756.270 0.000 -0.555 -0.552
ar.L3 0.9988 0.001 1637.052 0.000 0.998 1.000
ma.L1 0.4502 0.005 84.534 0.000 0.440 0.461
ma.L2 0.9885 0.005 192.509 0.000 0.978 0.999
sigma2 0.0250 0.001 32.710 0.000 0.024 0.027
===================================================================================
Ljung-Box (L1) (Q): 79.54 Jarque-Bera (JB): 62.18
Prob(Q): 0.00 Prob(JB): 0.00
Heteroskedasticity (H): 0.80 Skew: 0.38
Prob(H) (two-sided): 0.00 Kurtosis: 2.86
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.46
MAE 16592.0
MSE 374061878.0
RMSE 19341.0
MAPE 9.34 %
Wenn die vierten Ordnungen verwendet werden, handelt es sich bereits um ein sehr großes Modell mit 16 Koeffizienten. Ein derart umfangreiches Modell sollte eigentlich nicht verwendet werden, wird hier allerdings trotzdem betrachtet. Der MAPE fällt zwar auf 3,19%, da die Log-Likelihood mit 3.052 und das AIC mit -6.070 nur gering verbessert werden, ist hier von einer Überanpassung auszugehen. Dies wird auch durch die vielen, insignifikanten Lags deutlich.
#Nicht-saisonale und saisonale Ordnung festlegen
order = (4, 0, 4) #p, d, q
seasonal_order = (4, 0, 4, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
=========================================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(4, 0, 4)x(4, 0, 4, 7) Log Likelihood 3051.985
Date: Thu, 03 Feb 2022 AIC -6069.971
Time: 10:46:34 BIC -5970.579
Sample: 01-01-2015 HQIC -6033.928
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 1.1421 1.041 1.097 0.272 -0.898 3.182
ar.L2 -0.3893 0.923 -0.422 0.673 -2.198 1.420
ar.L3 0.0967 0.540 0.179 0.858 -0.961 1.154
ar.L4 0.0956 0.157 0.608 0.543 -0.212 0.404
ma.L1 -0.4393 1.042 -0.422 0.673 -2.481 1.603
ma.L2 -0.0008 0.477 -0.002 0.999 -0.935 0.933
ma.L3 0.1254 0.472 0.266 0.790 -0.799 1.050
ma.L4 -0.1285 0.129 -0.995 0.320 -0.382 0.125
ar.S.L7 -0.9954 0.107 -9.278 0.000 -1.206 -0.785
ar.S.L14 0.1197 0.077 1.557 0.119 -0.031 0.270
ar.S.L21 1.0622 0.074 14.377 0.000 0.917 1.207
ar.S.L28 0.8134 0.109 7.456 0.000 0.600 1.027
ma.S.L7 1.0490 0.096 10.946 0.000 0.861 1.237
ma.S.L14 -0.0797 0.073 -1.084 0.278 -0.224 0.064
ma.S.L21 -1.0623 0.069 -15.340 0.000 -1.198 -0.927
ma.S.L28 -0.8268 0.096 -8.625 0.000 -1.015 -0.639
sigma2 0.0054 6.85e-05 79.140 0.000 0.005 0.006
===================================================================================
Ljung-Box (L1) (Q): 0.14 Jarque-Bera (JB): 16374.12
Prob(Q): 0.71 Prob(JB): 0.00
Heteroskedasticity (H): 0.82 Skew: -2.02
Prob(H) (two-sided): 0.00 Kurtosis: 14.72
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.89
MAE 5345.0
MSE 76339076.0
RMSE 8737.0
MAPE 3.19 %
Beim ARIMA([1,2,6],0,2)(3,0,2)7 werden nur die durch ACF/PACF als stark korrelierten Lags verwendet. Der MAPE ist mit 3,20% sehr ähnlich wie beim initialen Modell, auch Log-Likelihood ist sehr ähnlich. Das Modell verwendet allerdings zwei zusätzliche Lags, weshalb das AIC auf -6.048 ansteigt (-6.058 beim initialen Modell). Es ist hier also von einer Überanpassung auszugehen.
#Nicht-saisonale und saisonale Ordnung festlegen
order = ([1,2,6], 0, 2) #p, d, q
seasonal_order = (3, 0, 2, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
=================================================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX([1, 2, 6], 0, 2)x(3, 0, 2, 7) Log Likelihood 3034.997
Date: Thu, 03 Feb 2022 AIC -6047.994
Time: 10:48:34 BIC -5983.682
Sample: 01-01-2015 HQIC -6024.672
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 0.5495 0.096 5.748 0.000 0.362 0.737
ar.L2 0.2772 0.071 3.905 0.000 0.138 0.416
ar.L6 0.0862 0.021 4.116 0.000 0.045 0.127
ma.L1 0.1439 0.097 1.491 0.136 -0.045 0.333
ma.L2 -0.2396 0.020 -12.241 0.000 -0.278 -0.201
ar.S.L7 0.0924 0.105 0.882 0.378 -0.113 0.298
ar.S.L14 0.9635 0.112 8.631 0.000 0.745 1.182
ar.S.L21 -0.0565 0.020 -2.769 0.006 -0.096 -0.016
ma.S.L7 0.0017 0.100 0.017 0.987 -0.194 0.197
ma.S.L14 -0.9373 0.097 -9.643 0.000 -1.128 -0.747
sigma2 0.0054 6.2e-05 87.186 0.000 0.005 0.006
===================================================================================
Ljung-Box (L1) (Q): 0.71 Jarque-Bera (JB): 15870.20
Prob(Q): 0.40 Prob(JB): 0.00
Heteroskedasticity (H): 0.80 Skew: -1.97
Prob(H) (two-sided): 0.00 Kurtosis: 14.55
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.89
MAE 5352.0
MSE 77214864.0
RMSE 8787.0
MAPE 3.2 %
Beim ARIMA(3,0,2)(2,0,2)7 wird ein größeres AR-Modul verwendet. Es zeigt sich ein ähnliches Verhalten wie beim ARIMA([1,2,6],0,2)(3,0,2)7, das Modell passt sich aufgrund der zusätzlichen Lags etwas stärker an die Trainingsdaten an, weshalb das AIC ansteigt. Gleichzeitig fällt die Güte des Modells aber ab. Es ist also auch hier von Überanpassungen auszugehen.
#Nicht-saisonale und saisonale Ordnung festlegen
order = (3, 0, 2) #p, d, q
seasonal_order = (2, 0, 2, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
=========================================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(3, 0, 2)x(2, 0, 2, 7) Log Likelihood 3029.471
Date: Thu, 03 Feb 2022 AIC -6038.941
Time: 10:50:03 BIC -5980.475
Sample: 01-01-2015 HQIC -6017.739
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 0.4968 0.045 11.083 0.000 0.409 0.585
ar.L2 0.7728 0.059 13.089 0.000 0.657 0.889
ar.L3 -0.3140 0.036 -8.798 0.000 -0.384 -0.244
ma.L1 0.1842 0.041 4.469 0.000 0.103 0.265
ma.L2 -0.6583 0.040 -16.628 0.000 -0.736 -0.581
ar.S.L7 0.0182 0.186 0.098 0.922 -0.347 0.383
ar.S.L14 0.9816 0.186 5.272 0.000 0.617 1.347
ma.S.L7 0.0071 0.191 0.037 0.970 -0.368 0.382
ma.S.L14 -0.9551 0.186 -5.145 0.000 -1.319 -0.591
sigma2 0.0056 6.55e-05 84.794 0.000 0.005 0.006
===================================================================================
Ljung-Box (L1) (Q): 1.42 Jarque-Bera (JB): 15713.60
Prob(Q): 0.23 Prob(JB): 0.00
Heteroskedasticity (H): 0.82 Skew: -2.00
Prob(H) (two-sided): 0.00 Kurtosis: 14.46
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.89
MAE 5388.0
MSE 77675555.0
RMSE 8813.0
MAPE 3.22 %
Selbiges geschieht beim einem ARIMA([1,2,4],0,2)(2,0,2)7. Das Modell passt sich etwas besser an die Trainingsdaten an, erzielt sogar einen leicht besseren MAPE von 2,17%, allerdings steigt das AIC auf -6.043 an. ARIMA(2,0,2)(2,0,2)7 lässt sich also nicht durch zusätzliche Lags verbessern, ohne das Überanpassungen auftreten.
#Nicht-saisonale und saisonale Ordnung festlegen
order = ([1,2,4], 0, 2) #p, d, q
seasonal_order = (2, 0, 2, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
=================================================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX([1, 2, 4], 0, 2)x(2, 0, 2, 7) Log Likelihood 3031.378
Date: Thu, 03 Feb 2022 AIC -6042.756
Time: 10:51:16 BIC -5984.290
Sample: 01-01-2015 HQIC -6021.555
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 0.4958 0.226 2.192 0.028 0.053 0.939
ar.L2 0.3562 0.141 2.530 0.011 0.080 0.632
ar.L4 0.0416 0.056 0.743 0.457 -0.068 0.151
ma.L1 0.2061 0.226 0.911 0.362 -0.237 0.649
ma.L2 -0.2821 0.026 -10.778 0.000 -0.333 -0.231
ar.S.L7 0.0082 0.008 1.071 0.284 -0.007 0.023
ar.S.L14 0.9918 0.008 129.803 0.000 0.977 1.007
ma.S.L7 0.0063 0.009 0.708 0.479 -0.011 0.024
ma.S.L14 -0.9892 0.009 -108.617 0.000 -1.007 -0.971
sigma2 0.0056 6.75e-05 82.348 0.000 0.005 0.006
===================================================================================
Ljung-Box (L1) (Q): 0.66 Jarque-Bera (JB): 15145.25
Prob(Q): 0.42 Prob(JB): 0.00
Heteroskedasticity (H): 0.82 Skew: -1.91
Prob(H) (two-sided): 0.00 Kurtosis: 14.30
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.89
MAE 5325.0
MSE 76400831.0
RMSE 8741.0
MAPE 3.17 %
Da sich ARIMA(2,0,2)(2,0,2)7 nicht durch weitere Lags verbessern lässt, wird nun versucht, ein gleichwertiges ARIMA-Modell mit weniger Lags zu erstellen.
Es wird zunächst versucht, alle Module auf die erste Ordnung zu verkleinern. Dadurch steigt der MAPE allerdings leicht auf 3,28% an. Gleichzeitig fällt Log-Likelihood auf 2.979 und das AIC steigt auf -5.947, es liegt also eine leichte Unteranpassung vor.
#Nicht-saisonale und saisonale Ordnung festlegen
order = (1, 0, 1) #p, d, q
seasonal_order = (1, 0, 1, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
=========================================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(1, 0, 1)x(1, 0, 1, 7) Log Likelihood 2978.545
Date: Thu, 03 Feb 2022 AIC -5947.089
Time: 10:56:42 BIC -5917.856
Sample: 01-01-2015 HQIC -5936.489
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 0.9000 0.009 101.035 0.000 0.883 0.917
ma.L1 -0.2587 0.014 -17.852 0.000 -0.287 -0.230
ar.S.L7 1.0000 2.87e-05 3.49e+04 0.000 1.000 1.000
ma.S.L7 -0.9823 0.005 -179.991 0.000 -0.993 -0.972
sigma2 0.0057 6.49e-05 88.450 0.000 0.006 0.006
===================================================================================
Ljung-Box (L1) (Q): 8.58 Jarque-Bera (JB): 15387.21
Prob(Q): 0.00 Prob(JB): 0.00
Heteroskedasticity (H): 0.83 Skew: -1.95
Prob(H) (two-sided): 0.01 Kurtosis: 14.37
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.89
MAE 5509.0
MSE 79731584.0
RMSE 8929.0
MAPE 3.28 %
Wenn die MA- und SMA-Module verkleinert werden, führt dies ebenfalls zu einer Unteranpassung, da MAPE auf 3,32% und Log-Likelihood auf 2.956 fallen. Das AIC verschlechtert sich auf -5.898. Die höhere Abweichung ist also nicht durch die geringere Komplexität des Modells zu rechtfertigen.
#Nicht-saisonale und saisonale Ordnung festlegen
order = (2, 0, 1) #p, d, q
seasonal_order = (2, 0, 1, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
=========================================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(2, 0, 1)x(2, 0, 1, 7) Log Likelihood 2955.786
Date: Thu, 03 Feb 2022 AIC -5897.572
Time: 10:57:53 BIC -5856.646
Sample: 01-01-2015 HQIC -5882.731
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 -0.1886 0.028 -6.857 0.000 -0.243 -0.135
ar.L2 0.8071 0.023 34.718 0.000 0.762 0.853
ma.L1 0.9980 0.026 39.125 0.000 0.948 1.048
ar.S.L7 1.0820 0.019 58.336 0.000 1.046 1.118
ar.S.L14 -0.0820 0.019 -4.427 0.000 -0.118 -0.046
ma.S.L7 -0.9813 0.006 -165.628 0.000 -0.993 -0.970
sigma2 0.0059 6.75e-05 87.756 0.000 0.006 0.006
===================================================================================
Ljung-Box (L1) (Q): 11.68 Jarque-Bera (JB): 15081.80
Prob(Q): 0.00 Prob(JB): 0.00
Heteroskedasticity (H): 0.80 Skew: -1.66
Prob(H) (two-sided): 0.00 Kurtosis: 14.42
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.88
MAE 5618.0
MSE 82022843.0
RMSE 9057.0
MAPE 3.32 %
Das gleiche gilt, wenn die AR- und SAR-Module verkleinert werden. Es kommt ebenfalls zu einer Unteranpassung, da MAPE auf 3,34% und Log-Likelihood auf 2.981 fallen. Das AIC verschlechtert sich auf -5.949. Die höhere Abweichung ist also nicht durch die geringere Komplexität des Modells zu rechtfertigen.
#Nicht-saisonale und saisonale Ordnung festlegen
order = (1, 0, 2) #p, d, q
seasonal_order = (1, 0, 2, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
=========================================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(1, 0, 2)x(1, 0, 2, 7) Log Likelihood 2981.889
Date: Thu, 03 Feb 2022 AIC -5949.778
Time: 10:59:48 BIC -5908.852
Sample: 01-01-2015 HQIC -5934.937
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 0.9996 0.000 3041.839 0.000 0.999 1.000
ma.L1 -0.2683 0.010 -26.584 0.000 -0.288 -0.248
ma.L2 -0.2781 0.016 -17.216 0.000 -0.310 -0.246
ar.S.L7 0.9991 0.000 2466.019 0.000 0.998 1.000
ma.S.L7 -0.9888 0.017 -58.485 0.000 -1.022 -0.956
ma.S.L14 0.0215 0.017 1.297 0.195 -0.011 0.054
sigma2 0.0058 7.06e-05 81.487 0.000 0.006 0.006
===================================================================================
Ljung-Box (L1) (Q): 0.00 Jarque-Bera (JB): 11391.49
Prob(Q): 0.98 Prob(JB): 0.00
Heteroskedasticity (H): 0.77 Skew: -1.48
Prob(H) (two-sided): 0.00 Kurtosis: 12.91
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.89
MAE 5547.0
MSE 79807735.0
RMSE 8934.0
MAPE 3.34 %
Wenn die MA- und SMA-Module deaktiviert werden, führt dies zu einer stärkeren Verschlechterung. Der MAPE steigt auf 3,82%. Die Log-Likelihood fällt sehr stark auf 2.599 ab, dementsprechend steigt auch das AIC auf -5.188 an. Es handelt sich hier also um eine sehr starke Unteranpassung.
#Nicht-saisonale und saisonale Ordnung festlegen
order = (2, 0, 0) #p, d, q
seasonal_order = (2, 0, 0, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
=========================================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(2, 0, 0)x(2, 0, 0, 7) Log Likelihood 2598.973
Date: Thu, 03 Feb 2022 AIC -5187.946
Time: 11:00:46 BIC -5158.713
Sample: 01-01-2015 HQIC -5177.345
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 0.6850 0.012 55.839 0.000 0.661 0.709
ar.L2 0.0320 0.016 1.982 0.048 0.000 0.064
ar.S.L7 0.5163 0.010 51.161 0.000 0.497 0.536
ar.S.L14 0.4262 0.010 42.369 0.000 0.406 0.446
sigma2 0.0077 0.000 67.443 0.000 0.008 0.008
===================================================================================
Ljung-Box (L1) (Q): 0.11 Jarque-Bera (JB): 6302.48
Prob(Q): 0.73 Prob(JB): 0.00
Heteroskedasticity (H): 0.79 Skew: -0.70
Prob(H) (two-sided): 0.00 Kurtosis: 10.56
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.84
MAE 6571.0
MSE 114039493.0
RMSE 10679.0
MAPE 3.82 %
Dieses Verhalten zeigt sich bei der Deaktivierung der AR- und SAR-Module noch viel deutlicher. Der MAPE schießt auf 8,94% in die Höhe. Die Log-Likelihood fällt auf 1.149 und dementsprechend steigt das AIC auf -2.289 an. Es handelt sich hier also um eine sehr starke Unteranpassung.
#Nicht-saisonale und saisonale Ordnung festlegen
order = (0, 0, 2) #p, d, q
seasonal_order = (0, 0, 2, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
=========================================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(0, 0, 2)x(0, 0, 2, 7) Log Likelihood 1147.878
Date: Thu, 03 Feb 2022 AIC -2285.756
Time: 11:01:57 BIC -2256.523
Sample: 01-01-2015 HQIC -2275.156
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ma.L1 0.9766 0.016 60.978 0.000 0.945 1.008
ma.L2 0.3793 0.018 21.181 0.000 0.344 0.414
ma.S.L7 0.8319 0.015 56.527 0.000 0.803 0.861
ma.S.L14 0.5287 0.015 35.880 0.000 0.500 0.558
sigma2 0.0236 0.001 37.864 0.000 0.022 0.025
===================================================================================
Ljung-Box (L1) (Q): 245.74 Jarque-Bera (JB): 584.72
Prob(Q): 0.00 Prob(JB): 0.00
Heteroskedasticity (H): 0.85 Skew: 0.16
Prob(H) (two-sided): 0.02 Kurtosis: 5.32
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.41
MAE 16291.0
MSE 412332149.0
RMSE 20306.0
MAPE 8.94 %
Wenn die nicht-saisonalen Module deaktiviert werden, tritt ebenfalls eine Unteranpassung auf, allerdings ist sie weniger stark ausgeprägt. Der MAPE steigt dennoch auf 6,02%. Die Log-Likelihood fällt auf 1.965, das AIC steigt auf -3.920 an.
#Nicht-saisonale und saisonale Ordnung festlegen
order = (0, 0, 0) #p, d, q
seasonal_order = (2, 0, 2, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
====================================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(2, 0, [1, 2], 7) Log Likelihood 1965.244
Date: Thu, 03 Feb 2022 AIC -3920.488
Time: 11:05:55 BIC -3891.255
Sample: 01-01-2015 HQIC -3909.887
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.S.L7 1.6491 0.016 105.378 0.000 1.618 1.680
ar.S.L14 -0.6491 0.016 -41.481 0.000 -0.680 -0.618
ma.S.L7 -1.1083 0.020 -54.619 0.000 -1.148 -1.068
ma.S.L14 0.1131 0.020 5.789 0.000 0.075 0.151
sigma2 0.0123 0.000 67.274 0.000 0.012 0.013
===================================================================================
Ljung-Box (L1) (Q): 1198.46 Jarque-Bera (JB): 4255.15
Prob(Q): 0.00 Prob(JB): 0.00
Heteroskedasticity (H): 1.07 Skew: -1.27
Prob(H) (two-sided): 0.31 Kurtosis: 8.79
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.69
MAE 10574.0
MSE 216492579.0
RMSE 14714.0
MAPE 6.02 %
Die auto_arima()-Funktion ermittelt mit einem ARIMA(0,0,0)(2,0,1)7 ein sehr ähnliches Modell, auch hier ist die deutliche Unteranpassung sofort ersichtlich.
model = auto_arima(y=endog, seasonal=True, m=7, d=0, D=0, start_p=0, start_q=0, max_p=0, max_q=0, information_criterion="aic", trace=True)
Performing stepwise search to minimize aic ARIMA(0,0,0)(1,0,1)[7] intercept : AIC=-3746.123, Time=1.85 sec ARIMA(0,0,0)(0,0,0)[7] intercept : AIC=-705.558, Time=0.18 sec ARIMA(0,0,0)(1,0,0)[7] intercept : AIC=-3630.295, Time=0.99 sec ARIMA(0,0,0)(0,0,1)[7] intercept : AIC=-2285.170, Time=0.50 sec ARIMA(0,0,0)(0,0,0)[7] : AIC=4297.801, Time=0.09 sec ARIMA(0,0,0)(2,0,1)[7] intercept : AIC=-3905.417, Time=4.30 sec ARIMA(0,0,0)(2,0,0)[7] intercept : AIC=-3699.382, Time=2.42 sec ARIMA(0,0,0)(2,0,2)[7] intercept : AIC=-3892.243, Time=5.33 sec ARIMA(0,0,0)(1,0,2)[7] intercept : AIC=-3864.293, Time=4.48 sec ARIMA(0,0,0)(2,0,1)[7] : AIC=inf, Time=2.64 sec Best model: ARIMA(0,0,0)(2,0,1)[7] intercept Total fit time: 22.787 seconds
#Nicht-saisonale und saisonale Ordnung festlegen
order = (0, 0, 0) #p, d, q
seasonal_order = (2, 0, 1, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
=================================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(2, 0, [1], 7) Log Likelihood 1960.965
Date: Thu, 03 Feb 2022 AIC -3913.930
Time: 11:04:41 BIC -3890.543
Sample: 01-01-2015 HQIC -3905.449
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.S.L7 1.5712 0.013 122.982 0.000 1.546 1.596
ar.S.L14 -0.5712 0.013 -44.717 0.000 -0.596 -0.546
ma.S.L7 -0.9917 0.005 -198.462 0.000 -1.001 -0.982
sigma2 0.0123 0.000 67.454 0.000 0.012 0.013
===================================================================================
Ljung-Box (L1) (Q): 1174.96 Jarque-Bera (JB): 4020.21
Prob(Q): 0.00 Prob(JB): 0.00
Heteroskedasticity (H): 1.06 Skew: -1.21
Prob(H) (two-sided): 0.37 Kurtosis: 8.65
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.69
MAE 10665.0
MSE 216783655.0
RMSE 14724.0
MAPE 6.06 %
Wenn die saisonalen Module abgeschaltet werden, führt dies zu einer sehr starken Unteranpassung. Der MAPE steigt auf 9,5% an, im Plot ist erkennbar, dass die wöchentliche Saisonalität nur noch schwer erkannt werden kann. Die Log-Likelihood erreicht mit 1.100 einen Tiefststand, das AIC ist mit -2.190 so hoch wie bei keinem anderen Modell.
#Nicht-saisonale und saisonale Ordnung festlegen
order = (2, 0, 2) #p, d, q
seasonal_order = (0, 0, 0, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
==============================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(2, 0, 2) Log Likelihood 1100.057
Date: Thu, 03 Feb 2022 AIC -2190.114
Time: 11:10:40 BIC -2160.881
Sample: 01-01-2015 HQIC -2179.513
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 0.9384 0.036 25.749 0.000 0.867 1.010
ar.L2 0.0612 0.036 1.691 0.091 -0.010 0.132
ma.L1 -0.1639 0.019 -8.543 0.000 -0.202 -0.126
ma.L2 -0.7352 0.016 -46.599 0.000 -0.766 -0.704
sigma2 0.0250 0.001 24.121 0.000 0.023 0.027
===================================================================================
Ljung-Box (L1) (Q): 0.39 Jarque-Bera (JB): 114.84
Prob(Q): 0.53 Prob(JB): 0.00
Heteroskedasticity (H): 0.83 Skew: -0.38
Prob(H) (two-sided): 0.01 Kurtosis: 2.30
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.46
MAE 16073.0
MSE 379065569.0
RMSE 19470.0
MAPE 9.5 %
Die auto_arima()-Funktion ermittelt mit ARIMA(2,0,5)(0,0,0)7 ein etwas umfangreicheres Modell, welches leicht besser ist als das ARIMA(2,0,2)(0,0,0)7. Allerdings liegt hier immer noch eine sehr starke Unteranpassung vor.
model = auto_arima(y=endog, seasonal=False, d=0, information_criterion="aic", trace=True)
Performing stepwise search to minimize aic ARIMA(2,0,2)(0,0,0)[0] : AIC=-2190.603, Time=1.09 sec ARIMA(0,0,0)(0,0,0)[0] : AIC=4297.801, Time=0.09 sec ARIMA(1,0,0)(0,0,0)[0] : AIC=-1190.569, Time=0.12 sec ARIMA(0,0,1)(0,0,0)[0] : AIC=1413.651, Time=0.12 sec ARIMA(1,0,2)(0,0,0)[0] : AIC=-2190.828, Time=0.73 sec ARIMA(0,0,2)(0,0,0)[0] : AIC=120.292, Time=0.22 sec ARIMA(1,0,1)(0,0,0)[0] : AIC=-1233.988, Time=0.18 sec ARIMA(1,0,3)(0,0,0)[0] : AIC=-2190.396, Time=0.89 sec ARIMA(0,0,3)(0,0,0)[0] : AIC=-196.997, Time=0.43 sec ARIMA(2,0,1)(0,0,0)[0] : AIC=-1449.273, Time=0.47 sec ARIMA(2,0,3)(0,0,0)[0] : AIC=-2219.065, Time=1.21 sec ARIMA(3,0,3)(0,0,0)[0] : AIC=inf, Time=1.73 sec ARIMA(2,0,4)(0,0,0)[0] : AIC=-2396.594, Time=1.41 sec ARIMA(1,0,4)(0,0,0)[0] : AIC=-2336.809, Time=1.12 sec ARIMA(3,0,4)(0,0,0)[0] : AIC=-2583.760, Time=1.70 sec ARIMA(4,0,4)(0,0,0)[0] : AIC=-2578.675, Time=1.86 sec ARIMA(3,0,5)(0,0,0)[0] : AIC=-2994.513, Time=2.10 sec ARIMA(2,0,5)(0,0,0)[0] : AIC=-2700.210, Time=1.68 sec ARIMA(4,0,5)(0,0,0)[0] : AIC=-2571.056, Time=2.11 sec ARIMA(3,0,5)(0,0,0)[0] intercept : AIC=-2999.828, Time=4.06 sec ARIMA(2,0,5)(0,0,0)[0] intercept : AIC=-3177.692, Time=3.31 sec ARIMA(1,0,5)(0,0,0)[0] intercept : AIC=-2401.321, Time=2.81 sec ARIMA(2,0,4)(0,0,0)[0] intercept : AIC=-2854.727, Time=2.92 sec ARIMA(1,0,4)(0,0,0)[0] intercept : AIC=-2112.299, Time=1.24 sec ARIMA(3,0,4)(0,0,0)[0] intercept : AIC=-2551.947, Time=3.49 sec Best model: ARIMA(2,0,5)(0,0,0)[0] intercept Total fit time: 37.113 seconds
#Nicht-saisonale und saisonale Ordnung festlegen
order = (2, 0, 5) #p, d, q
seasonal_order = (0, 0, 0, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
==============================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(2, 0, 5) Log Likelihood 1357.619
Date: Thu, 03 Feb 2022 AIC -2699.238
Time: 11:12:31 BIC -2652.465
Sample: 01-01-2015 HQIC -2682.276
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 0.5017 0.036 13.914 0.000 0.431 0.572
ar.L2 0.4912 0.036 13.670 0.000 0.421 0.562
ma.L1 0.3121 0.029 10.832 0.000 0.256 0.369
ma.L2 -0.8661 0.016 -53.774 0.000 -0.898 -0.835
ma.L3 -0.6953 0.024 -28.920 0.000 -0.742 -0.648
ma.L4 0.2166 0.016 13.189 0.000 0.184 0.249
ma.L5 0.5502 0.016 34.770 0.000 0.519 0.581
sigma2 0.0204 0.001 27.117 0.000 0.019 0.022
===================================================================================
Ljung-Box (L1) (Q): 0.04 Jarque-Bera (JB): 21.93
Prob(Q): 0.84 Prob(JB): 0.00
Heteroskedasticity (H): 0.80 Skew: -0.02
Prob(H) (two-sided): 0.00 Kurtosis: 2.55
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.55
MAE 14806.0
MSE 310385489.0
RMSE 17618.0
MAPE 8.59 %
Beim ARIMA(4,0,2)(0,0,0)7 werden mehr signifikante Lags in das AR-Modul einbezogen, allerdings zeigt sich auch hier eine starke Unteranpassung.
#Nicht-saisonale und saisonale Ordnung festlegen
order = (4, 0, 2) #p, d, q
seasonal_order = (0, 0, 0, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
==============================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(4, 0, 2) Log Likelihood 1138.758
Date: Thu, 03 Feb 2022 AIC -2263.515
Time: 11:13:28 BIC -2222.589
Sample: 01-01-2015 HQIC -2248.674
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 0.7944 0.033 24.286 0.000 0.730 0.859
ar.L2 -0.6855 0.019 -36.529 0.000 -0.722 -0.649
ar.L3 1.1305 0.018 61.396 0.000 1.094 1.167
ar.L4 -0.2395 0.032 -7.397 0.000 -0.303 -0.176
ma.L1 0.4237 0.007 61.152 0.000 0.410 0.437
ma.L2 0.9804 0.007 144.977 0.000 0.967 0.994
sigma2 0.0238 0.001 33.141 0.000 0.022 0.025
===================================================================================
Ljung-Box (L1) (Q): 0.03 Jarque-Bera (JB): 139.25
Prob(Q): 0.86 Prob(JB): 0.00
Heteroskedasticity (H): 0.78 Skew: 0.53
Prob(H) (two-sided): 0.00 Kurtosis: 3.43
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test)
Vorhersage
R2 0.49
MAE 15513.0
MSE 354910331.0
RMSE 18839.0
MAPE 8.67 %
Das ARIMA(2,0,2)(2,0,2)7 lässt sich durch zusätzliche Lags nicht verbessern, da stets Überanpassungen eintreten. Die zusätzlichen Lags rechtfertigen die höhere Komplexität nicht. Andererseits lässt sich das Modell auch nicht durch weniger Lags in seiner Komplexität reduzieren, ohne dass es zu Unteranpassungen kommt. Es hat sich außerdem gezeigt, dass alle vier Module (AR, MA, SAR und SMA) für das Modell relevant sind, da sich keines der Module ohne starke Unteranpassungen abschalten lässt. Die AR-Module sind allerdings etwas wichtiger. Außerdem tragen die saisonalen Module etwas mehr zum Modell bei als die nicht-saisonalen Module.
Das ARIMA(2,0,2)(2,0,2)7 kann die Zeitreihe bereits gut abbilden, die wöchentliche und jährliche Saisonalität kann abgebildet werden. Es kommt allerdings stellenweise zu großen Abweichungen. DER MAPE liegt mit 3,21% unter der Baseline und dem Erfolgskriterium. An den Autokorrelationen der Residuen lassen sich keine Systematiken bei den Abweichungen erkennen.
#Nicht-saisonale und saisonale Ordnung festlegen
order = (2, 0, 2) #p, d, q
seasonal_order = (2, 0, 2, 7) #P, D, Q, m
#Modell mit Trainingsdaten erstellen
train_model_config = SARIMAX(endog=endog_train, order=order, seasonal_order=seasonal_order)
train_model = train_model_config.fit()
#Modell mit allen Daten erstllen und Konfiguration/Koeffizienten von ersten Modell übernehmen (kein neues Training)
model_config = SARIMAX(endog=endog, order=order, seasonal_order=seasonal_order)
model = model_config.filter(train_model.params)
#Modell ausgeben
print(model.summary())
print()
SARIMAX Results
=========================================================================================
Dep. Variable: verbrauch No. Observations: 2557
Model: SARIMAX(2, 0, 2)x(2, 0, 2, 7) Log Likelihood 3037.805
Date: Thu, 03 Feb 2022 AIC -6057.610
Time: 11:15:04 BIC -6004.991
Sample: 01-01-2015 HQIC -6038.529
- 12-31-2021
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 0.9434 0.050 18.823 0.000 0.845 1.042
ar.L2 0.0162 0.045 0.358 0.720 -0.072 0.105
ma.L1 -0.2361 0.051 -4.665 0.000 -0.335 -0.137
ma.L2 -0.2770 0.022 -12.526 0.000 -0.320 -0.234
ar.S.L7 0.0215 0.056 0.383 0.702 -0.088 0.131
ar.S.L14 0.9783 0.056 17.455 0.000 0.868 1.088
ma.S.L7 0.0038 0.052 0.074 0.941 -0.098 0.106
ma.S.L14 -0.9595 0.051 -18.780 0.000 -1.060 -0.859
sigma2 0.0055 6.28e-05 87.433 0.000 0.005 0.006
===================================================================================
Ljung-Box (L1) (Q): 0.02 Jarque-Bera (JB): 15797.82
Prob(Q): 0.89 Prob(JB): 0.00
Heteroskedasticity (H): 0.81 Skew: -1.94
Prob(H) (two-sided): 0.00 Kurtosis: 14.54
===================================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
#Vorhersage erzeugen
scaled_preds_test = model.predict(start="2021-01-1", end="2021-12-31", dynamic=False).values
#Vorhersagen mit echten Werten vergleichen
functions.custom_metrics_arima(y_true, scaled_preds_test, True, True, True, True)
Vorhersage
R2 0.89
MAE 5379.0
MSE 77296958.0
RMSE 8792.0
MAPE 3.21 %